package framework.view.components
{
import flash.display.DisplayObject;
import flash.display.MovieClip;
import flash.display.Sprite;
import flash.events.Event;
import flash.text.TextField;
import flash.utils.ByteArray;
import flash.utils.Dictionary;

import framework.core.ComponentBuilder;
import framework.core.ComponentParser;
import framework.core.UIWidget;
import framework.injection.IInjectable;
import framework.proxy.IComponentProxy;
import framework.view.components.button.ButtonProxy;
import framework.view.components.button.StateButtonProxy;
import framework.view.components.container.RepeaterProxy;

import mx.utils.UIDUtil;

/**
 * Component
 * @author jliang
 * 
 */
public class Component extends Sprite implements IComponent, IInjectable
{
	//==========================================================================
	//  Constructor
	//==========================================================================
	public function Component()
	{
		super();
		xmlDoc = embedDesignFile();
	}
	//==========================================================================
	//  Variables
	//==========================================================================
	private static var XML_DOC_MAP:Dictionary = new Dictionary(true);
	
	public var xmlDoc:XML; 
	
	public var componentID:String;
	
	protected var parser:ComponentParser;
	
	protected var proxys:Dictionary;  /* ComponentProxy */
	
	protected function get proxyMapping():Array
	{
		return [];
	}
	
	protected var skin:MovieClip;
	
	protected function get skinReference():String
	{
		return null;
	}
	
	public function get cacheClassDesc():Boolean
	{
		return false;
	}
	
	protected var _isDisposeWhenRemove:Boolean = false;
	
	public function get isDisposeWhenRemove():Boolean
	{
		return _isDisposeWhenRemove;
	}
	
	public function set isDisposeWhenRemove(value:Boolean):void
	{
		_isDisposeWhenRemove = value;
		
		if (value)
		{
			this.addEventListener(Event.REMOVED_FROM_STAGE, removeFromStageHandler);
		}
		else
		{
			this.removeEventListener(Event.REMOVED_FROM_STAGE, removeFromStageHandler);
		}
	}
	
	//==========================================================================
	//  Public methods
	//==========================================================================
	public function initialize():void
	{
		if (xmlDoc)
		{
			parser = new ComponentParser();
			parser.parse(this);
		}		
		if (skinReference)
		{
			skin = UIWidget.createUI(skinReference) as MovieClip;
			addChild(skin);
			var temp:Array = proxyMapping;
			for each (var proxyDef:Object in temp)
			{				
				var def:Array = String(proxyDef.skin).split(".");
				var tempSkin:DisplayObject = skin;
				for (var i:int = 0; i < def.length; i++)
				{
					tempSkin = (def[i] != "" ? tempSkin[def[i]] : skin);
				}
				
				if (tempSkin is TextField && proxyDef.hasOwnProperty("text"))
				{
					TextField(tempSkin).text = proxyDef.text;
				}
				
				if (proxyDef.hasOwnProperty("classRef"))
				{
					var proxyRef:Class = proxyDef.classRef as Class;
					var proxy:IComponentProxy = ComponentBuilder.create(proxyRef);
					
					if (proxy is RepeaterProxy)
					{
						if (proxyDef.hasOwnProperty("renderProxyRef"))
						{
							RepeaterProxy(proxy).renderProxyRef = proxyDef.renderProxyRef as Class;
						}
						if (proxyDef.hasOwnProperty("onItemSelected"))
						{
							RepeaterProxy(proxy).onItemSelected = proxyDef.onItemSelected as Function;
						}
					}
					
					if (proxyDef.method) 
					{
						proxy[proxyDef.method](tempSkin);
					}
					else
					{
						proxy.parse(tempSkin as MovieClip);
					}
					
					if (proxy is ButtonProxy)
					{
						if (proxyDef.hasOwnProperty("onClick"))
						{
							ButtonProxy(proxy).onClick = proxyDef.onClick as Function;
						}
						if (proxyDef.hasOwnProperty("onMouseOut"))
						{
							ButtonProxy(proxy).onMouseOut = proxyDef.onMouseOut as Function;
						}
						if (proxyDef.hasOwnProperty("onMouseOver"))
						{
							ButtonProxy(proxy).onMouseOver = proxyDef.onMouseOver as Function;
						}
					}
					
					if (proxy is StateButtonProxy)
					{
						if (proxyDef.hasOwnProperty("onSelected"))
						{
							StateButtonProxy(proxy).onSelected = proxyDef.onSelected as Function;
						}
						if (proxyDef.hasOwnProperty("onMouseOut"))
						{
							StateButtonProxy(proxy).onMouseOut = proxyDef.onMouseOut as Function;
						}
						if (proxyDef.hasOwnProperty("onMouseOver"))
						{
							StateButtonProxy(proxy).onMouseOver = proxyDef.onMouseOver as Function;
						}
					}
					
					if (Object(proxy).hasOwnProperty("text") && proxyDef.hasOwnProperty("text"))
					{
						proxy["text"] = proxyDef.text;
					}
					
					if (!proxys) proxys = new Dictionary(true);
					if (!proxyDef.id)
					{
						proxyDef.id = UIDUtil.createUID();
					}
					proxys[proxyDef.id] = proxy;
					proxy.id = proxyDef.id;
				}
				
			}
		}
	}
	
	public function commitProperty():void
	{
		
	}
	
	public function dispose():void
	{
		this.removeEventListener(Event.REMOVED_FROM_STAGE, removeFromStageHandler);
		
		if (skin)
		{
			skin.stop();
		}
		
		if (parser) parser.dispose();
		
		for each (var proxy:IComponentProxy in proxys)
		{
			proxy.dispose();
		}
		
		proxys = null;
		
		ComponentBuilder.disposeComponent(this);
	}
	
	protected function embedDesignFile():XML
	{
		return null;
	}
	
	protected function generateDesignDoc(classRef:Class):XML
	{
		var xml:XML;
		var ba:ByteArray;
		if (cacheClassDesc)
		{
			xml = XML_DOC_MAP[classRef];
			if (!xml)
			{
				ba = (new classRef()) as ByteArray;
				xml = new XML(ba.readUTFBytes(ba.length));
				XML_DOC_MAP[classRef] = xml;
			}
		}
		else
		{
			ba = (new classRef()) as ByteArray;
			xml = new XML(ba.readUTFBytes(ba.length));
		}		
		return xml;
	}
	
	protected function removeFromStageHandler(event:Event):void
	{
		this.dispose();
	}
}
}